Java 8 数据流
- 衔接操作:filter、map、sorted
- 终止操作:anyMatch、forEach、collect、Count、Reduce
ps:任何的流操作都不会影响原来的数据结构。
1.获取数据流
集合.stream()
或者 Stream.of()
List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
stringCollection.stream().forEach(System.out::println);
Stream.of(stringCollection).forEach(System.out::println);
2.处理顺序
衔接操作的一个重要特性就是延迟性。这是因为衔接操作只在终止操作调用时被执行。
//无结果返回
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
});
//间隔输出filter、foreach
Stream.of("d2", "a2", "b1", "b3", "c")
.filter(s -> {
System.out.println("filter: " + s);
return true;
}).forEach(s -> System.out.println("forEach:" + s));
}
所以:有终止操作可以减少衔接的操作,比如anyMatch,不会每个元素都映射一次。
Stream.of("d2", "a2", "b1", "b3", "c")
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.anyMatch(s -> {
System.out.println("anyMatch: " + s);
return s.startsWith("A");
});
执行就是流水线式执行,如果衔接操作过程过滤了,那么终止操作也没法执行了。多个衔接操作就要考虑他们的顺序,可以直接影响执行的次数了。
3.复用数据流
按照我们正常的想法,可以复用变量。
List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
Stream<String> stream = stringCollection.stream();
stream.forEach(s -> System.err.println("forEach" + s));
stream.forEach(s -> System.out.println("forEach" + s));
报错
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at stream.复用.main(复用.java:26)
解决方案:创建一个数据流供应器,来构建新的数据流,并且设置好所有衔接操作:
stringCollection.stream().forEach(s -> System.out.println("forEach" + s));
Supplier<Stream<String>> streamSupplier = new Supplier() {
@Override
public Object get() {
return stringCollection.stream();
}
};
streamSupplier.get().forEach(System.out::println);
常用的方法
- 1.filter 过滤
stringCollection.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);
其中filter 需要一个Predicate 对象
Predicate predicate = new Predicate() {
@Override
public boolean test(Object o) {
return false;
}
};
2.sorted 排序
stringCollection.stream().sorted((a,b) -> b.compareTo(a)).forEach(System.out::println);
3.Map转换
这个 map 转换是
不会去重
的,和 hashmap 不一样。stringCollection.stream().map(String::toUpperCase).sorted((a,b) -> b.compareTo(a)).forEach(System.out::println);
4.Match
boolean anyMatch = stringCollection.stream().anyMatch(s -> s.startsWith("s")); System.out.println(anyMatch);
5.Count
long count = stringCollection.stream().filter(s -> s.startsWith("a")).count(); System.out.println(count);
6.Reduce 归约操作将所有流中的元素组合为单一结果。 ifPresent 有值返回true,没值false
stringCollection.stream().sorted().reduce((s1, s2) -> s1 + "#" + s2).ifPresent(System.out::println); // 2组参数,返回第一个参数的类型 List<String> list = ImmutableList.of("1", "2", "3", "4", "5", "6"); String s = list.stream().reduce("a232rrr",(i1, i2) -> i1 += i2); //a232rrr123456
7.collect
Set<String> collect = stringCollection.stream().collect(Collectors.toSet()); collect.forEach(System.out::println);
8.flatMap 拆开
// flatMap 就是拆开 Stream<List<Integer>> inputStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6)); inputStream.flatMap(childList -> childList.stream()).collect(Collectors.toList());
图解:
9.IntStream 封闭范围
//封闭范围 区间 [0,1] IntStream.rangeClosed(0,1).forEach(item ->{ System.out.println(item); }); //封闭范围 区间 [0,5) IntStream.range(0,5).forEach(System.out::println);
← Java8 时间日期 函数式接口→